/**
* AutoSWF - Cody Cushing. March 26, 2009
* Copyright (c) 2009 Cody Cushing
* No use restrictions. Maintain this notice in all versions. 
**/

package com.autoswf.automator
{
	import com.autoswf.core.Delimiters;
	import com.autoswf.core.Link;
	import com.autoswf.core.Transport;
	
	import flash.events.Event;
	import flash.utils.Dictionary;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;

	/**
	 * Observes the tree for events to record via an IAutomationClient. Sends events down the tree for running functional tests.
	 */
	public class AutomationObserver extends Link implements IAutomationObserver
	{
		protected static const NODE_SCHEMA:XML = <node delay="" className="" type="" path=""/>;
		protected static const DELIMITER:String = Delimiters.PATH_DELIMITER;
		
		protected var _clients:Dictionary;
		
		
		/**
		 * Constructor.
		 */
		public function AutomationObserver(id:String)
		{
			super(id);
			_clients = new Dictionary();
		}
		
		
		public function addSubscriber(client:IAutomationClient):void
		{
			_clients[client] = client;
			client.observer = this;
		}
		
		
		public function hasSubscriber(client:IAutomationClient):Boolean
		{
			return (_clients[client] != null)
		}
		
		
		public function removeSubscriber(client:IAutomationClient):void
		{
			delete _clients[client];
		}
		
		
		/** Serialize an object into an xml descriptor node and pass it to the AutomationClient. */
		override public function sendUp(object:*):void
		{
			var transport:Transport = object;
			
			var node:XML = NODE_SCHEMA;
			
			if(transport.message is Event)
			{
				var event:Event = transport.message;
				node.@className = getQualifiedClassName(event);
				node.@type = event.type;
			}
			node.@path = transport.toString();
			node.@delay = interval;
			
			for each(var client:IAutomationClient in _clients)
			{
				client.handle(node.toXMLString());
			}
		}
		
		
		/**
		 * Receive a descriptor, deserialize into an object (event), pass down the tree via its path property.
		 * 
		 * @param descriptor  A stringified xml node of this format: 
		 * <node className="" type="" path=""/>
		 */
		public function notify(descriptor:String):void
		{
			var node:XML = XML(descriptor);
			var transport:Transport;
			
			if(node.@className)
			{
				var classDef:Class = Class(getDefinitionByName(node.@className));
				var event:Event = new classDef(node.@type);
				var path:String = node.@path.toString(); 
				path = path.replace(DELIMITER + node.@type, "");
				
				transport = new Transport(event).setPath(path);
			}
			else
			{
				transport = new Transport(node.@path);
			}
			sendDown(transport);
		}
		

		protected var _lastTime:uint = new Date().time;
		protected function get interval():uint
		{
			var newTime:uint = new Date().time;
			var interval:uint = newTime - _lastTime;
			_lastTime = newTime;
			return interval;
		}

	}
}